----------------------------------------------------------------------------------
-- Company: 
-- Engineer: 
-- 
-- Create Date:    14:52:38 04/02/2008 
-- Design Name: 
-- Module Name:    STAGE_IF - Behavioral 
-- Project Name: 
-- Target Devices: 
-- Tool versions: 
-- Description: 
--
-- Dependencies: 
--
-- Revision: 
-- Revision 0.01 - File Created
-- Additional Comments: 
--
----------------------------------------------------------------------------------
LIBRARY IEEE;
USE IEEE.STD_LOGIC_1164.ALL;
USE IEEE.STD_LOGIC_ARITH.ALL;
USE IEEE.STD_LOGIC_UNSIGNED.ALL;

ENTITY STAGE_IF IS
  PORT ( CLK          : IN  std_logic;
         RST          : IN  std_logic;
         EXMEM_COND   : IN  std_logic;
         EXMEM_ALUOUT : IN  std_logic_vector(15 DOWNTO 0);
         IFID_NPC     : OUT std_logic_vector(7 DOWNTO 0);
         IFID_IR      : OUT std_logic_vector(31 DOWNTO 0));
END STAGE_IF;

ARCHITECTURE Behavioral OF STAGE_IF IS
  COMPONENT instruction_memory
    PORT (
      clka  : IN  std_logic;
      addra : IN  std_logic_vector(7 DOWNTO 0);
      douta : OUT std_logic_vector(31 DOWNTO 0));
  END COMPONENT;
  SIGNAL pc :     std_logic_vector(7 DOWNTO 0) := (OTHERS => '0');
  SIGNAL ir :     std_logic_vector(31 DOWNTO 0);  -- Instruction Register
BEGIN
  -----------------------------------------------------------------------------
  -- External Connections
  IFID_IR  <= ir;
  IFID_NPC <= pc;

  -----------------------------------------------------------------------------
  -- Instruction Memory
  inst_memory : instruction_memory
    PORT MAP (
      clka  => CLK,
      addra => pc,
      douta => ir);

  -----------------------------------------------------------------------------
  -- Program Counter (PC)
  -- purpose: Handle the program counter values
  -- type   : sequential
  -- inputs : CLK, RST, pc
  -- outputs: pc
  PROCESS (CLK) IS
  BEGIN  -- PROCESS
    IF CLK'event AND CLK = '1' THEN     -- rising clock edge
      IF RST = '1' THEN                 -- synchronous reset (active high)
        pc   <= (OTHERS => '0');
      ELSE
        -- Test to see if the instruction in EXMEM register is a branch, and
        -- whether or not it was taken
        IF EXMEM_COND = '1' THEN
          pc <= EXMEM_ALUOUT(7 DOWNTO 0);
        ELSE
          pc <= pc + 1;                 -- Note since we use 4 byte words, we just increment
        END IF;
      END IF;
    END IF;
  END PROCESS;
END Behavioral;

